#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <signal.h>

#include "modbus_dev_driver.h"
#include "uart_driver.h"
#include "cmd_deal.h"
#include "usb_hotplug_check.h"
#include "env_ctrol_service.h"
#include "common.h"
#include "tcpServer.h"
#include "duYa_Curtain_Ctrl_Driver.h"
#include "somfy_Curtain_Ctrl_Driver.h"

int GlobalChannnel = 0x00;


///////////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************************
*
*函数名:
*作用：窗帘电机串行控制
*参数:devid ：设备地址
*参数：
*	     prototype : 协议支持 ，协议类型定义
*		  devid    : 设备id编码
*	     funcode  ： 功能码
*	     startaddr ： 数据在点表中的起始位置
*		 num      ： 数据个数
*		 pvalue  ： 数据存储区域
*
*
*返回值:0:失败 !0：成功         	
**有数据要读取时 返回读取到的字节数 ，没数据要读取时返回已发送的字节数
*
*************************************************************************************************/
int curtain_motor_device_control_info(int prototype,int devid,int funcode,int startaddr,int num,int *pvalue)
{

	uint8_t channel = 0x00;
	uint32_t ret = 0x00;
	
	uint32_t len = 0x00;

	if (devid < 0x01)
	{
		return 0x00;
	}

	/*获取控制通道*/
	ret = cmd_get_device_control_channel(prototype,&channel);
	if (ret == 0x01)
	{
		return 0x00;
	}
	ret = 0x00;
	
	/*等待发送空闲状态 :最长等待时间 2s*/
	ret = cmd_wait_send_idle_state_timeout(channel,200);
	if (ret == 0x00)
	{
		return 0x00;
	}
	ret = 0x00;
	
	/**/
	cmd_send_data(prototype,devid,0,funcode,startaddr,num,pvalue,channel);

	/*数据发送结果 :正常接收到返回信息 非0*/
	len = ttl_send_data(channel);
	if ((int)len > 0)
	{

		LOGD("env ctrol service ,curtain data send ok");
		
		/*读取接收到的数据到缓冲区*/
		ret = cmd_read_data(prototype,devid,0,funcode,startaddr,num,pvalue);
	}

	cmd_clear_send_state(channel,SEND_IDLE_STATUS);
	cmd_clear_recv_state(channel,RECV_IDLE_STATUS);

	/*有数据要读取时 返回读取到的字节数 ，没数据要读取时返回已发送的字节数*/
	return (ret > 0 ? ret:len);
}

///////////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************************
*
*函数名:
*作用：读取窗帘电机信息
*参数:devid ：设备地址
*参数：
*	     prototype : 协议支持 ，协议类型定义
*		  devid    : 设备id编码
*	     funcode  ： 功能码
*	     startaddr ： 数据在点表中的起始位置
*		 num      ： 数据个数
*		 pvalue  ： 数据存储区域
*
*
*返回值:0:失败 !0：成功
*
*************************************************************************************************/
int curtain_motor_device_read_data(int prototype,int devid,int funcode,int startaddr,int num,int *pvalue)
{
	return 0x00;
}


/*******************************************************************************************
*
*函数名:
*作用：查询设备信息
*参数:devid ：设备地址
*	   datatype： 数据类型 : 0 ：线圈  1:输入位 2:保持寄存器 3：输入寄存器
	     startaddr ：要查询数据在点表中的起始位置
		num ：要查询的数据个数
		*pvalue ：查询结果存储位置
*
*
*返回值:0:失败 !0：成功
*
*************************************************************************************************/
int get_modbus_device_Info(int devid,int datatype,int startaddr,int num,int *pvalue)
{

	uint8_t channel = 0x00;

	uint32_t i = 0x00;
	uint32_t ret = 0x00;

	uint32_t len = 0x00;
	uint32_t tmp = 0x00;
	
	if (devid < 0x01)
	{
		return 0x00;
	}

	/*获取控制通道*/
	ret = cmd_get_device_control_channel(0,&channel);
	if (ret == 0x01)
	{
		return 0x00;
	}
	ret = 0x00;

	/*等待发送空闲状态 :最长等待时间 2s*/
	ret = cmd_wait_send_idle_state_timeout(channel,200);
	if (ret == 0x00)
	{
		return 0x00;
	}
	
	/**/
	len = cmd_send_data(0,devid,0,datatype,startaddr,num,NULL,channel);
	if (len >0)
	{
		ret = ttl_send_data(channel);
	}
	cmd_clear_send_state(channel,SEND_IDLE_STATUS);
	cmd_clear_recv_state(channel,RECV_IDLE_STATUS);
	
	if ((int)ret > 0x00)
	{		
		/*读取到要查询的数据*/
		switch(datatype)
		{
			case 0x00:
			case 0x01:
			{
				
				for (i = 0;i < num;i ++)
				{
					tmp = ((ModbusDevStru.inputandcoilstatus.all[(startaddr + i)/ 32] >> ((startaddr + i) % 32)) & 0x00000001);
					pvalue[i] = tmp;
				}
			}
			break;

			case 0x02:
			case 0x03:
			{
				for (i = 0;i < num;i ++)
				{
					pvalue[i] = ModbusDevStru.holdandindatareg[(startaddr + i)];
				}
			}
			break;

			default :
				break;
		}
	}
	else
	{
	    memset(pvalue,0,sizeof(int) * num);
	}
	return (ret < 0?0:ret);
}

/*******************************************************************************************
*
*函数名:
*作用：设置设备信息
*参数:devid ：设备地址
*	   datatype： 数据类型 : 0 ：线圈  1:输入位 2:保持寄存器 3：输入寄存器
	     startaddr ：要查询数据在点表中的起始位置
		num ：要查询的数据个数
		*pvalue ：等待设置的设备数据
*
*
*返回值:0:失败 !0:成功
*
*************************************************************************************************/

int set_modbus_device_Info(int devid,int datatype,int startaddr,int num,int *pvalue)
{

	uint8_t channel = 0x00;
	uint32_t i = 0x00;
	
	uint32_t len = 0x00;
	uint32_t ret = 0x00;
	
    uint32_t tmp = 0x00;
	
	//printf ("entry set modbus device info 123123123\n");
	if (devid < 0x01)
	{
		return 0;
	}

	/*获取控制通道*/
	ret = cmd_get_device_control_channel(0,&channel);
	if (ret == 0x01)
	{
		return 0x00;
	}
	ret = 0x00;

	/*等待发送空闲状态 :最长等待时间 2s*/
	ret = cmd_wait_send_idle_state_timeout(channel,200);
	if (ret == 0x00)
	{
		return 0;
	}

	//printf ("entry set modbus device info \n");
	switch(datatype)
	{
		case 0x00:
		{

			for (i = 0;i < num;i ++)
			{
				tmp =  pvalue[i];
				tmp &= 0x00000001;
				
				ModbusDevStru.inputandcoilstatus.all[(startaddr + i) / 32] &= ~(0x1 << ((startaddr + i) % 32));
				ModbusDevStru.inputandcoilstatus.all[(startaddr + i) / 32] |= tmp << ((startaddr + i) % 32);
			}
		}
			break;

		case 0x02:
		{

			for (i = 0;i < num;i ++)
			{
				ModbusDevStru.holdandindatareg[(startaddr + i)] = pvalue[i] ;
			}
		}
			break;

		case 0x01:
		case 0x03:
		default:
			break;

	}

	len = cmd_send_data(0,devid,0x01,datatype,startaddr,num,NULL,channel);
	if (len >0)
	{
		ret = ttl_send_data(channel);
	}
	
	cmd_clear_send_state(channel,SEND_IDLE_STATUS);
	cmd_clear_recv_state(channel,RECV_IDLE_STATUS);

	return (ret<0?0:ret);
}

/*
 * 设备在线状态查询
 *
 *返回值 0 ：设备离线 1：设备在线
 *
 *
 * */
int get_modbus_device_online_status(uint8_t devid)
{
	return 0x00;
}


/*多串口 处理线程*/
void * usb_serial_device_recv_handle(void * arg)
{

	int ret = 0x00;
    uint8_t channelid = (uint8_t)*(int*)arg;

	LOGD("entry usb serial device recv handle !\n");
    LOGD("channel id %d!\n",channelid);

	while(1)
	{
		ret = ttl_recv_data(channelid);
		if (ret < 0x00)
		{
			break;
		}
	}

    LOGD("exit pthread ttl recv ");
	return 0;
}

/**
 * *函数：init_usb_serail_device_server
 * *    功能： 初始化usb串口设备
 * *    参数：     channel ：串口设备对应的数据传输通道
 **				prototype：数据传输协议类型 : 0 :modbus  
 **				bautrate :串口对应的波特率				
 * *    返回值  ：初始化成功 >= 0 ，失败 < 0
 * *
 * */
int init_usb_serail_device_server(uint8_t prototype,uint8_t channel,uint32_t bautrate)
{

	int ret = 0x00;
	switch (prototype)
	{
	    case SERIAL_BUS_MODBUS_RTU:
        {
           ret =  init_modbus_device_server(channel,bautrate);
        }
            break;

        case SERIAL_BUS_DUYA_CURTAIN:
        {
			ret = init_duya_curtain_device_server(channel,bautrate);
        }
            break;

        case SERIAL_BUS_SOMFY_CURTAIN:
        {
			ret = init_somfy_curtain_device_server(channel,bautrate);
        }
            break;

        default:
        {
            LOGD("device prototyepe not support!");
            ret = -1;
        }
	}
    return ret;
}

/**
*函数：init_modbus_device_server
*作用： 初始化串口服务  
* 参数 : channel ：串口设备对应的数据输出通道
*		buatrate: 串口设备对应的波特率
**/
int init_modbus_device_server(uint8_t channel,uint32_t buatrate)
{
    int ret = 0x00;
    pthread_t pthread_serial_recv_id;

	/*当前通道是否已经被初始化完成 ： 如果初始化 完成的话，不用再次进行初始化操作
     * 								如果未进行初始化，则需要对设备进行初始化操作。
     * */
	/*任一通道进行数据传输*/
	if (channel == 0xff)
	{
		channel = check_usable_usb_serial_channel();
		if ((int8_t)channel >= 0x00 )
		{
			modbus_device_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);
			return 0x00;
		}
	}
	else{
		if(get_usb_serial_device_status(channel) == USB_SERIAL_INIT_OK)
		{
			modbus_device_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);
			return 0x00;
		}
	}

    cmd_init(channel);

    ret = init_hotplug_struct(channel,buatrate);
    if (ret < 0)
    {
        LOGD("init hotplug fail\n");
		modbus_device_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_FAIL);

        return ret ;
    }
    ret = usb_serial_init_by_channel(&channel);
    if (ret < 0)
    {
        LOGD("modbus device ......usb serial init fail!\n");
		modbus_device_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_FAIL);

        return (-1);
    }
	modbus_device_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);

	/*串口初始化成功:返回0*/	
    LOGD("modbus device.....usb serial init ok!\n");

    GlobalChannnel = channel;

    pthread_create(&pthread_serial_recv_id, NULL, &usb_serial_device_recv_handle, (void *)&GlobalChannnel);
    pthread_detach(pthread_serial_recv_id);

	return 0;
}

/**
*函数：init_duya_curtain_device_server
*作用： 初始化串口服务  
* 参数 : channel ：串口设备对应的数据输出通道
*		buatrate: 串口设备对应的波特率
**/
int init_duya_curtain_device_server(uint8_t channel,uint32_t buatrate)
{

    int ret = 0x00;
    pthread_t pthread_serial_recv_id;

	/*当前通道是否已经被初始化完成 ： 如果初始化 完成的话，不用再次进行初始化操作
     * 								如果未进行初始化，则需要对设备进行初始化操作。
     * */
	/*任一通道进行数据传输*/
	if (channel == 0xff)
	{
		channel = check_usable_usb_serial_channel();
		if ((int8_t)channel >= 0x00 )
		{
			duya_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);
			return 0x00;
		}
	}
	else{
		if(get_usb_serial_device_status(channel) == USB_SERIAL_INIT_OK)
		{
			duya_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);
			return 0x00;
		}
	}


	cmd_init(channel);
    ret = init_hotplug_struct(channel,buatrate);
    if (ret < 0)
    {

        LOGD("init hotplug fail\n");
		duya_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_FAIL);

        return ret ;
    }
    ret = usb_serial_init_by_channel(&channel);
    if (ret < 0)
    {

        LOGD("duya curtain ......usb serial init fail!\n");
		duya_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_FAIL);

        return (-1);
    }
	duya_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);

	/*串口初始化成功:返回0*/	
    LOGD("duya curtain.....usb serial init ok!\n");

    GlobalChannnel = channel;

    pthread_create(&pthread_serial_recv_id, NULL, &usb_serial_device_recv_handle, (void *)&GlobalChannnel);
    pthread_detach(pthread_serial_recv_id);

	return 0;
}

/**
*函数：init_somfy_curtain_device_server
*作用： 初始化串口服务  
* 参数 : channel ：串口设备对应的数据输出通道
*		buatrate: 串口设备对应的波特率
**/
int init_somfy_curtain_device_server(uint8_t channel,uint32_t buatrate)
{

	uint8_t i = 0x00;
    int ret = 0x00;
    pthread_t pthread_serial_recv_id;

	/*当前通道是否已经被初始化完成 ： 如果初始化 完成的话，不用再次进行初始化操作
     * 								如果未进行初始化，则需要对设备进行初始化操作。
     * */
	/*任一通道进行数据传输*/
	if (channel == 0xff)
	{
		channel = check_usable_usb_serial_channel();
		if ((int8_t)channel >= 0x00 )
		{
			somfy_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);
			return 0x00;
		}
	}
	else{
		if(get_usb_serial_device_status(channel) == USB_SERIAL_INIT_OK)
		{
			somfy_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);
			return 0x00;
		}
	}

	cmd_init(channel);
    ret = init_hotplug_struct(channel,buatrate);
    if (ret < 0)
    {
        LOGD("init hotplug fail\n");
		somfy_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_FAIL);

        return ret ;
    }
    ret = usb_serial_init_by_channel(&channel);
    if (ret < 0)
    {
        LOGD("somfy curtain ......usb serial init fail!\n");
		somfy_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_FAIL);

		return (-1);
    }
	somfy_curtain_control_init(channel,buatrate,USB_SERIAL_DEVICE_INIT_OK);

	/*串口初始化成功:返回0*/	
    LOGD("somfy curtain.....usb serial init ok!\n");

    GlobalChannnel = channel;

    pthread_create(&pthread_serial_recv_id, NULL, &usb_serial_device_recv_handle, (void *)&GlobalChannnel);
    pthread_detach(pthread_serial_recv_id);

	return 0;
}


int init_usbserial_hotplug_server(void)
{

    pthread_t pthread_usb_device_hotplug_check_id;

	UsbSerialHotplugDetectionStru.usbserialinsertflag = 0x00;

    hotplug_sock = init_hotplug_sock();
    if(hotplug_sock < 0)
    {
        /*netlink 初始化失败*/
        return (-1);
    }

    pthread_create(&pthread_usb_device_hotplug_check_id, NULL, &usb_device_hotplug_check_handle, NULL);
    /* 线程分离，结束时自动回收线程 */
    pthread_detach(pthread_usb_device_hotplug_check_id);

    return 0;

}

int init_TCP_server(void)
{

    int i = 0x10;
    pthread_t pthread_TCP_server_id;

    /*init listen ip port */
    int ret = 0x00;

    do{
        ret = init_tcp_server_param();
        if (ret > 0x00)
        {
            break;
        }
        sleep (10);
    }while(i--);

    if (i == 0x00)
    {
        return -1;
    }

    LOGI("init tcp server ret:%d",ret);

    pthread_create(&pthread_TCP_server_id, NULL, tcp_server_proc, NULL);
    /* 线程分离，结束时自动回收线程 */
    pthread_detach(pthread_TCP_server_id);

    return 0;
}


/**
*自测程序 调用接口 适用于linux系统
*
*
**/
#if DEBUG_PLATFORM == 0x01
void * demo_test_jni_handle(void *arg)
{

	int status = 0x00;
	int usbserialstatus = 0x00;
	int tmp[32] = {0x00};

	int lightvalue = 0x00;

	while(1)
	{

		printf ("entry set modbus device inf aaaaaa\n");

		ModbusDevStru.moddevid = IR_SENSOR_ID;
		get_modbus_device_Info(ModbusDevStru.moddevid,2,0x03,1,tmp);

		ModbusDevStru.moddevid = DIKONG_LIGHT_MODULATOR;
		printf ("tmp[0]:%d,ModbusDevStru.holdandindatareg[3]:%d\n",tmp[0],ModbusDevStru.holdandindatareg[ALARM_STATES]);

		if (ModbusDevStru.holdandindatareg[ALARM_STATES]== 0x01)
		{

			tmp[0] = 400;
			set_modbus_device_Info(ModbusDevStru.moddevid,2,DIMING_VALUES_2 ,0x01,tmp);
			sleep(1);
		
		
			tmp[0] = 800;
			set_modbus_device_Info(ModbusDevStru.moddevid,2,DIMING_VALUES_2 ,0x01,tmp);

			ModbusDevStru.holdandindatareg[ALARM_STATES] = 0x00;
			sleep(1);
		}
		
		/*光照度 :测量*/	
		ModbusDevStru.moddevid = DIKONG_LIGHT_MODULATOR;		
		get_modbus_device_Info(ModbusDevStru.moddevid,2,ILLUMINANCE_MEASURED,1,tmp);

		lightvalue =  tmp[0];
		printf ("light value :%d , ModbusDevStru.holdandindatareg[5]:%d\n",lightvalue,ModbusDevStru.holdandindatareg[ILLUMINANCE_MEASURED]);
	
		if (lightvalue > 1000)
		{

			tmp[0] = 0x0;
			tmp[1] = 0x0;		
			tmp[2] = 0x0;

			ModbusDevStru.moddevid = SHIJU_LIGHT_MODULATOR_ID;
			set_modbus_device_Info(ModbusDevStru.moddevid,2,FIRST_COIL_ADDRESS,3,tmp);

			sleep(1);
			
			tmp[0] = 0x01;
			tmp[1] = 0x01;
			tmp[2] = 0x01;
			
			set_modbus_device_Info(ModbusDevStru.moddevid,2,FIRST_COIL_ADDRESS,3,tmp);

			sleep(1);
		}

		/*光照度传感器 :测量*/
		ModbusDevStru.moddevid = ILLUMINANCE_SENSOR_ID;
		get_modbus_device_Info(ModbusDevStru.moddevid,2,0X03,3,tmp);

		printf ("光照度最大值 : %d, 光照度实际测量值 :%d\n",ModbusDevStru.holdandindatareg[0x03],ModbusDevStru.holdandindatareg[0x05]);

		
		ModbusDevStru.moddevid = SHIJU_LIGHT_MODULATOR_ID;
		get_modbus_device_Info(ModbusDevStru.moddevid,2,0x03,1,tmp);

		usbserialstatus = get_usb_serial_device_status();
		printf ("usbserialstatus :%d\n",usbserialstatus);
		
		sleep(1);

	}
}

int init_test_jni(void)
{

    int ret = 0x00;

    pthread_t pthread_test_jni_id;

	printf ("pthread test jni init ok!\n");
	
    pthread_create(&pthread_test_jni_id, NULL, &demo_test_jni_handle, NULL);
    //pthread_join(pthread_test_jni_id,NULL);
    pthread_detach(pthread_test_jni_id);

	return 0;
}

void * demo_modbus_device_service_monitor_handle(void *arg)
{
	while(1)
	{
	
		if (UsbSerialHotplugDetectionStru.usbserialhotplugstats == USB_SERIAL_INSERT_OK)
		{
			init_modbus_device_server();
		}
		sleep(0x05);
	}
}

void init_modbus_device_service_monitor(void)
{

    int ret = 0x00;

    pthread_t pthread_modbus_device_service_monitor_id;

	printf ("pthread modbus device service monitor!\n");
	
    pthread_create(&pthread_modbus_device_service_monitor_id, NULL, &demo_modbus_device_service_monitor_handle, NULL);
    pthread_join(pthread_modbus_device_service_monitor_id,NULL);

}

int main()
{

	init_modbus_device_server();
	init_usbserial_hotplug_server();

	init_test_jni();

	init_modbus_device_service_monitor();

    return 0;
}
#endif
